#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "lrtsp_stream.h"
#include "rtsp_client.h"
#include "rtsp_request_reponse.h"

#define RECV_BUFFER_SIZE 4096

struct RtspClient
{
	int fd;
	char* revf_buffer;

	unsigned int rtsp_cseq;
	char* hostname;
	char* filename;

	int rtp_port;
	int rtcp_port;
	int rtp_ser_port;
	int rtcp_ser_port;

	unsigned int ssrc;
	unsigned short seq;
	unsigned int timestamp;

	RtspTransportMode transport_mode;
	int session_id;
};

int _rtsp_method_match_handle(struct RtspClient* thiz, RtspMethod method)
{
	switch(method)
	{
        case RTSP_OPTIONS:
            if(rtsp_options(thiz) < 0){
                return -1;
            }
            else{
				printf("options command response  sucessfull\n");
            }
            break;
		case RTSP_DESCRIBE:
			if(rtsp_describe(thiz)<=0){
				return -1;
			}
			else{
				printf("describe command response	sucessfull\n");
			}
			break;
		case RTSP_SETUP:
			if(rtsp_setup(thiz) <= 0){
				printf("setup command response not sucessfull\n");
				return -1;
			}
			else{
				 printf("setup command response  sucessfull\n");
			}
			break;
		case RTSP_PLAY:
			if(rtsp_play(thiz) < 0){
				printf("play command response not sucessfull\n");
				return -1;
			}
			else{
				printf("play command response	 sucessfull\n");
				lrtsp_stream_add_rtsp_client(thiz);
			}
			break;
		case RTSP_TERARDOWN:
			if(rtsp_terardown(thiz) <= 0){
				printf("terardown command response not sucessfull\n");
				return -1;
			}
			else{
			    lrtsp_stream_remove_rtsp_client(thiz);
				printf("terardown command response	sucessfull\n");
				return -1;
			}
			break;
		case RTSP_INVALID_METHOD:	
		    printf("Error:RTSP_INVALID_METHOD \n");
			rtsp_send_reply(thiz, 400);
			break;
		default:
			return -1;
			break;
    }

    return 0;
}


/*@return -1 close the rtsp client*/
int rtsp_client_dispatch(struct RtspClient* thiz)
{
	int ret = -1;
    RtspMethod rtsp_method;

	/*read the  fd */
	ret = read(thiz->fd, thiz->revf_buffer, RECV_BUFFER_SIZE);
	if(ret > 0){
		printf("recv buffer(%s)\n", thiz->revf_buffer);
		rtsp_method = get_rtsp_method(thiz->revf_buffer);
        ret = _rtsp_method_match_handle(thiz, rtsp_method);
		return ret;
	}

	if(ret == 0){
        return -1;
	}

	return 0;
}

struct RtspClient* rtsp_client_create(int fd)
{
	struct RtspClient* thiz = NULL;

	thiz = (struct RtspClient*)malloc(sizeof(struct RtspClient));

	thiz->fd = fd;
	thiz->revf_buffer = (char*)malloc(RECV_BUFFER_SIZE);
	
	return thiz;
}

void rtsp_client_destroy(struct RtspClient* thiz)
{
	if(thiz){
	    if(thiz->fd > 0){
            close(thiz->fd);
	    }
	    if(thiz->filename != NULL){
            free(thiz->filename);
	    }
	    if(thiz->hostname != NULL){
            free(thiz->hostname);
	    }
	    free(thiz);    
	}

	return;
}

int rtsp_client_get_fd(struct RtspClient* thiz)
{
	if(thiz){
		return thiz->fd;
	}

	return -1;
}

int rtsp_client_set_cseq(struct RtspClient* thiz, unsigned int cseq)
{
	if(thiz){
		thiz->rtsp_cseq = cseq;
		return 0;
	}

	return -1;
}

int rtsp_client_get_cseq(struct RtspClient* thiz)
{
	if(thiz){
		return thiz->rtsp_cseq;
	}

	return -1;
}


char* rtsp_client_recv_request_string(struct RtspClient* thiz)
{
	if(thiz){
		return thiz->revf_buffer;
	}	

	return NULL;
}

int rtsp_client_set_filename(struct RtspClient* thiz, char* filename)
{
	if(thiz && filename != NULL){
		thiz->filename = strdup(filename);
		return 0;
	}

	return -1;
}

char* rtsp_client_get_filename(struct RtspClient* thiz)
{
	if(thiz){
		return thiz->filename;
	}

	return NULL;
}

int rtsp_client_set_hostname(struct RtspClient* thiz, char* hostname)
{
	if(thiz && hostname != NULL){
		thiz->hostname = strdup(hostname);
		return 0;
	}

	return -1;
}

char* rtsp_client_get_hostname(struct RtspClient* thiz)
{
	if(thiz){
		return thiz->hostname;
	}

	return NULL;
}

int rtsp_client_set_rtp_port(struct RtspClient* thiz, int rtp_port)
{
	if(thiz)
	{
		thiz->rtp_port = rtp_port;
		return 0;
	}

	return -1;
}

int rtsp_client_get_rtp_port(struct RtspClient* thiz)
{
	if(thiz)
	{
		return thiz->rtp_port;
	}

	return -1;
}

int rtsp_client_set_rtcp_port(struct RtspClient* thiz, int rtcp_port)
{
    if(thiz){
        return thiz->rtcp_port = rtcp_port;
    }
    
    return 0;
}

int rtsp_client_get_rtcp_port(struct RtspClient* thiz)
{
    if(thiz){
        return thiz->rtcp_port;
    }

    return -1;
}


int rtsp_client_set_rtp_ser_port(struct RtspClient* thiz, int rtp_ser_port)
{
	if(thiz){
		thiz->rtp_ser_port = rtp_ser_port;
		return 0;
	}

	return -1;
}

int rtsp_client_get_rtp_ser_port(struct RtspClient* thiz)
{
	if(thiz){
		return thiz->rtp_ser_port;
	}

	return -1;
}

int rtsp_client_set_rtcp_ser_port(struct RtspClient* thiz, int rtcp_ser_port)
{
    if(thiz){
        return thiz->rtcp_port = rtcp_ser_port;
    }
    
    return 0;
}

int rtsp_client_get_rtcp_ser_port(struct RtspClient* thiz)
{
    if(thiz){
        return thiz->rtcp_ser_port;
    }

    return -1;
}

int rtsp_client_set_ssrc(struct RtspClient* thiz, unsigned int ssrc)
{
    if(thiz){
        return thiz->ssrc = ssrc;
    }

    return 0;
}

unsigned int rtsp_client_get_ssrc(struct RtspClient* thiz)
{
    if(thiz){
        return thiz->ssrc;         
    }

    return 0;
}

int rtsp_client_set_seq(struct RtspClient* thiz, unsigned short seq)
{
    if(thiz){
        return thiz->seq = seq;
    }

    return -1;
}

unsigned short rtsp_client_get_seq(struct RtspClient* thiz)
{
    if(thiz){
        return thiz->seq;
    }

    return -1;
}

int rtsp_client_set_timestamp(struct RtspClient* thiz, unsigned long timestamp)
{
    if(thiz){
        return thiz->timestamp = timestamp;   
    }

    return 0;
}

unsigned int rtsp_client_get_timestamp(struct RtspClient* thiz)
{
    if(thiz){
        return thiz->timestamp;
    }

    return 0;
}

int rtsp_client_set_transport_mode(struct RtspClient*thiz, RtspTransportMode  transport_mode)
{
    if(thiz){
        thiz->transport_mode = transport_mode;
    }

    return 0;
}

RtspTransportMode rtsp_client_get_transport_mode(struct RtspClient*thiz)
{
    if(thiz){
        return thiz->transport_mode;
    }

    return RTSP_TRANSPORT_BUTT;
    
}
int rtsp_client_set_session_id(struct RtspClient* thiz, int session_id)
{
    if(thiz){
        thiz->session_id = session_id;       
    }

    return 0;
}

int rtsp_client_get_session_id(struct RtspClient* thiz)
{
    if(thiz){
        return thiz->session_id;
    }
    
    return -1;
}


